// ============================================
// TypeScript 泛型示例
// ============================================

export {}

// 1. 基本泛型函数
function identity<T>(arg: T): T {
    return arg;
}

// 使用泛型函数
let output1 = identity<string>("hello");
let output2 = identity<number>(42);
let output3 = identity(true); // 类型推断

console.log(output1, output2, output3);

// 2. 泛型数组
function loggingIdentity<T>(arg: T[]): T[] {
    console.log(arg.length);
    return arg;
}

// 或者使用Array<T>
function loggingIdentity2<T>(arg: Array<T>): Array<T> {
    console.log(arg.length);
    return arg;
}

loggingIdentity([1, 2, 3]);
loggingIdentity2(["a", "b", "c"]);

// 3. 泛型类型
// 泛型函数类型
let myIdentity: <T>(arg: T) => T = identity;

// 使用对象字面量形式
let myIdentity2: { <T>(arg: T): T } = identity;

// 4. 泛型接口
interface GenericIdentityFn<T> {
    (arg: T): T;
}

let myIdentity3: GenericIdentityFn<number> = identity;
let myIdentity4: GenericIdentityFn<string> = identity;

// 5. 泛型类
class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
    
    constructor(zeroValue: T, addFn: (x: T, y: T) => T) {
        this.zeroValue = zeroValue;
        this.add = addFn;
    }
}

let myGenericNumber = new GenericNumber<number>(0, (x, y) => x + y);
console.log(myGenericNumber.add(5, 3));

let stringNumeric = new GenericNumber<string>("", (x, y) => x + y);
console.log(stringNumeric.add("Hello ", "World"));

// 6. 泛型约束
interface Lengthwise {
    length: number;
}

function loggingIdentity3<T extends Lengthwise>(arg: T): T {
    console.log(arg.length); // 现在我们知道arg有length属性
    return arg;
}

// loggingIdentity3(3); // 错误，number没有length属性
loggingIdentity3("hello");
loggingIdentity3([1, 2, 3]);
loggingIdentity3({ length: 10, value: 3 });

// 7. 在泛型约束中使用类型参数
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key];
}

let x = { a: 1, b: 2, c: 3, d: 4 };
let a = getProperty(x, "a"); // 正确
let b = getProperty(x, "b"); // 正确
// let m = getProperty(x, "m"); // 错误，'m'不存在于'x'中

console.log(a, b);

// 8. 在泛型中使用类类型
function create<T>(c: { new(): T }): T {
    return new c();
}

class BeeKeeper {
    hasMask: boolean = true;
}

class ZooKeeper {
    nametag: string = "Mikle";
}

class Animal {
    numLegs: number = 4;
}

class Bee extends Animal {
    keeper: BeeKeeper = new BeeKeeper();
}

class Lion extends Animal {
    keeper: ZooKeeper = new ZooKeeper();
}

function createInstance<A extends Animal>(c: new () => A): A {
    return new c();
}

let bee = createInstance(Bee);
let lion = createInstance(Lion);

console.log(bee.keeper.hasMask);
console.log(lion.keeper.nametag);

// 9. 条件类型
type NonNullable<T> = T extends null | undefined ? never : T;
type Example1 = NonNullable<string | number | undefined>; // string | number
type Example2 = NonNullable<string[] | null>; // string[]

// 分布式条件类型
type ToArray<Type> = Type extends any ? Type[] : never;
type StrArrOrNumArr = ToArray<string | number>; // string[] | number[]

// 10. 映射类型
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

type Partial<T> = {
    [P in keyof T]?: T[P];
};

interface Person {
    name: string;
    age: number;
    email: string;
}

type ReadonlyPerson = Readonly<Person>;
type PartialPerson = Partial<Person>;

let readonlyPerson: ReadonlyPerson = {
    name: "John",
    age: 30,
    email: "john@example.com"
};

// readonlyPerson.name = "Jane"; // 错误，只读属性

let partialPerson: PartialPerson = {
    name: "Jane" // 其他属性是可选的
};

// 11. 实用工具类型
// Pick<T, K> - 从T中选择属性K
type PersonName = Pick<Person, "name" | "age">;

// Omit<T, K> - 从T中排除属性K
type PersonWithoutEmail = Omit<Person, "email">;

// Record<K, T> - 创建一个类型，其属性键为K，属性值为T
type ThreeStringProps = Record<"prop1" | "prop2" | "prop3", string>;

let threeStrings: ThreeStringProps = {
    prop1: "value1",
    prop2: "value2",
    prop3: "value3"
};

// 12. 高级泛型模式
// 函数重载与泛型
function reverse<T>(items: T[]): T[];
function reverse(items: string): string;
function reverse<T>(items: T[] | string): T[] | string {
    if (typeof items === "string") {
        return items.split("").reverse().join("");
    } else {
        return items.slice().reverse();
    }
}

let reversedArray = reverse([1, 2, 3, 4]);
let reversedString = reverse("hello");

console.log(reversedArray, reversedString);

// 13. 泛型工厂模式
interface Constructable<T = {}> {
    new (...args: any[]): T;
}

function Timestamped<TBase extends Constructable>(Base: TBase) {
    return class extends Base {
        timestamp = Date.now();
    };
}

function Activatable<TBase extends Constructable>(Base: TBase) {
    return class extends Base {
        isActivated = false;
        
        activate() {
            this.isActivated = true;
        }
        
        deactivate() {
            this.isActivated = false;
        }
    };
}

class User {
    name = "";
}

// 组合多个mixins
const TimestampedUser = Timestamped(User);
const TimestampedActivatableUser = Timestamped(Activatable(User));

let user = new TimestampedActivatableUser();
user.name = "John";
user.activate();

console.log(user.name, user.timestamp, user.isActivated);

console.log("=== 泛型示例完成 ===");